using System;
using System.Collections.Generic;
using System.Text;
using SpoonCore2.Client;
using System.IO;
using System.Net;
using SpoonCore2.Message.Filter;
using SpoonCore2.Message.Header;
using SpoonCore2.Service;

namespace SpoonCore2.Message
{
	public class MessageHandler
	{
		public delegate void ReceiveMessageHandler<T>(ClientInfo sender, T message) where T : IMessage;

		private readonly SortedList<int, IHandlerItem> _handlers = new SortedList<int, IHandlerItem>();

		public void Register<T>(ReceiveMessageHandler<T> handler) where T : IMessage, new()
		{
			_handlers.Add(typeof(T).FullName.GetHashCode(), new HandlerItem<T>(handler));
		}

		public void Receive(IService service, ClientInfo info, BinaryReader reader, IList<IMessageOption> options, IList<IMessageFilterInfo> filters)
		{
			int messageId = reader.ReadInt32();
			if (_handlers.ContainsKey(messageId)) _handlers[messageId].Dispache(service, info, reader, options, filters);
		}

		private interface IHandlerItem
		{
			void Dispache(IService service, ClientInfo sender, BinaryReader reader, IList<IMessageOption> options, IList<IMessageFilterInfo> filters);
		}

		private class HandlerItem<T> : IHandlerItem where T : IMessage, new()
		{
			private readonly ReceiveMessageHandler<T> _handler;

			public HandlerItem(ReceiveMessageHandler<T> handler)
			{
				_handler = handler;
			}

			public void Dispache(IService service, ClientInfo sender, BinaryReader reader, IList<IMessageOption> options, IList<IMessageFilterInfo> filters)
			{
				T msg = new T();
				msg.SetBytes(service, reader);
				foreach (IMessageOption option in options)
				{
					msg.Options.Add(option);
				}
				foreach (IMessageFilterInfo filter in filters)
				{
					msg.Filters.Add(filter);
				}
				_handler(sender, msg);
			}
		}
	}
}